#ifndef VIDEOPLAYER_H
#define VIDEOPLAYER_H

#include <QObject>
#include <QWidget>
#include <string>
#include <QString>
#include <QQueue>
#include <QDateTime>
#include <QUrl>
#include <QMimeDatabase>
#include <QUuid>
#include <QTimer>
#include "ffinclude.h"
#include "playerdefine.h"

class DemuxThread;
class DecodeThread;
class RenderThread;

/*
    视频播放器
*/
class VideoPlayer : public QObject
{
    Q_OBJECT
public:
    static QString createMediaPreview(const QString& mediaFilePath,const QSize& size=QSize());
    static void queryMediaInfo(const QUrl& url,MediaInfo& mediaInfo);
    static QString dumpMediaInfo(const MediaInfo& media);

    enum PlayerState{
        Stoped,
        Playing,
        Paused
    };

public:
    explicit VideoPlayer(QObject* parent=nullptr);
    ~VideoPlayer();

    static bool init();
    static void deInit();

    //播放控制
    void play(MediaInfo media);
    void stop();
    void pause();
    void resume();
    bool step(qint64 num=1000);
    bool seek(qint64 pos);

    //播放设置
    PlayerConfig* config();
    MediaInfo mediaInfo();

    //播放器信息
    qint64 position();
    MediaInfo* media();
    PlayerState state();

    WId wId();
    void setWId(WId id);
    bool fill();
    void setFill(bool fill);
    double rate();
    void setRate(double rate);
    bool mute();
    void setMute(bool mute);
    int volume();
    void setVolume(int volume);
    bool enableHWA();
    void setEnableHWA(bool enable);
    bool showFirstFrame();
    void setShowFirstFrame(bool show);
    int posNotifyInterval();
    void setPosNotifyInterval(int intervalMs, bool notifyWithSec=true);
    void setRenderSize(QSize size);
    void setVideSinkName(const QString& vsink);

signals:
    void playerPlaying();                   //播放开始
    void playerPaused();                    //播放暂停
    void playerStopped();                   //播放停止
    void playerError(const QString& errMsg);//播放出现错误
    void playerEnded();                     //播放到达结尾
    void requestRetryPlay();                //指示需要重试播放操作
    void positionChanged(qint64 curPoss);   //播放进度改变

private slots :   
    void initPlayerInfo();
    void destoryPlayerInfo();

    void __error(const QString &errMsg);

    void onThreadInited();
    void onThreadError(const QString& errMsg);
    void onThreadExited();
    void onDemuxThreadEof();
    void onDemuxThreadSeekDone(bool success,const QString& errMsg);

    void onDemuxThreadInited();
    void onDemuxThreadError(const QString& errMsg);
    void onDemuxThreadExited();

    void onVideoDecodeThreadInited();
    void onVideoDecodeThreadError(const QString& errMsg);
    void onVideoDecodeThreadExited();

    void onAudioDecodeThreadInited();
    void onAudioDecodeThreadError(const QString& errMsg);
    void onAudioDecodeThreadExited();

    void onTextDecodeThreadInited();
    void onTextDecodeThreadError(const QString& errMsg);
    void onTextDecodeThreadExited();

    void onRenderThreadInited();
    void onRenderThreadError(const QString& errMsg);
    void onRenderThreadExited();

private:
    MediaInfo m_mediaInfo;
    PlayerInfo m_playerInfo;
    PlayerConfig m_playerConfig;

    DemuxThread* m_demuxThread;
    DecodeThread* m_vcodecThread;
    DecodeThread* m_acodecThread;
    DecodeThread* m_textcodecThread;
    RenderThread* m_renderThread;

    PlayerState m_state;
    QTimer m_endTimer;
    QTimer m_probeCheckTimer;
    QTimer m_posNotifyTimer;

    WId m_wid;

    QMimeDatabase m_mimeDb;
    int m_volume;
    bool m_mute;
    bool m_scaleWithFill;
    double m_rate;
    bool m_enableHWA;
    int m_posNotifyInterval;
    bool m_posNotifyWithSec;
    bool m_showFirstFrame;
    QSize m_renderSize;
    QString m_vsinkName;

    qint64 m_lastNotifyPos;
    bool m_isDestoryed;
    bool m_isReqPlay;
    bool m_isReqSeek;
    bool m_reqPause;

    int m_probeCheckInterval;
    int m_probeCheckMaxTimeout;
    int m_probeCheckMaxErrTimes;
    int m_probeCheckCurErrTimes;
    QDateTime m_probeLastDateTime;

    friend class DemuxThread;
    friend class DecodeThread;
    friend class RenderThread;
};

#endif // VIDEOPLAYER_H
